From cbb632d45510548238843411031df19b119e278a Mon Sep 17 00:00:00 2001 From: "cwc22@centipede.cl.cam.ac.uk" Date: Fri, 4 Mar 2005 02:00:12 +0000 Subject: [PATCH] bitkeeper revision 1.1236.9.1 (4227c12cJQxFhBUYk0ojkmnooUw0jQ) Grant tables work on data structures. --- .rootkeys | 1 + .../arch/xen/kernel/gnttab.c | 114 +++++++++++- .../include/asm-xen/gnttab.h | 4 + .../include/asm-xen/hypervisor.h | 2 +- tools/libxc/Makefile | 1 + tools/libxc/xc.h | 57 ++++++ tools/libxc/xc_gnttab.c | 143 +++++++++++++++ tools/libxc/xc_vmx_build.c | 4 +- xen/common/grant_table.c | 170 +++++++++++++++++- xen/include/public/grant_table.h | 23 +++ xen/include/xen/grant_table.h | 2 + 11 files changed, 512 insertions(+), 9 deletions(-) create mode 100644 tools/libxc/xc_gnttab.c diff --git a/.rootkeys b/.rootkeys index 996aac70b0..ef70f2ef87 100644 --- a/.rootkeys +++ b/.rootkeys @@ -542,6 +542,7 @@ 3fbba6dbasJQV-MVElDC0DGSHMiL5w tools/libxc/xc_domain.c 40278d99BLsfUv3qxv0I8C1sClZ0ow tools/libxc/xc_elf.h 403e0977Bjsm_e82pwvl9VvaJxh8Gg tools/libxc/xc_evtchn.c +4227c129ZKjJPNYooHVzBCyinf7Y6Q tools/libxc/xc_gnttab.c 40e03333Eegw8czSWvHsbKxrRZJjRA tools/libxc/xc_io.c 40e03333vrWGbLAhyJjXlqCHaJt7eA tools/libxc/xc_io.h 3fbba6dbNCU7U6nsMYiXzKkp3ztaJg tools/libxc/xc_linux_build.c diff --git a/linux-2.6.10-xen-sparse/arch/xen/kernel/gnttab.c b/linux-2.6.10-xen-sparse/arch/xen/kernel/gnttab.c index af892aeb2a..3780677908 100644 --- a/linux-2.6.10-xen-sparse/arch/xen/kernel/gnttab.c +++ b/linux-2.6.10-xen-sparse/arch/xen/kernel/gnttab.c @@ -6,6 +6,7 @@ * 2. Accessing others' memory reservations via grant references. * (i.e., mechanisms for both sender and recipient of grant references) * + * Copyright (c) 2005, Christopher Clark * Copyright (c) 2004, K A Fraser */ @@ -14,6 +15,9 @@ #include #include #include +#include +#include +#include #include #ifndef set_fixmap_ma @@ -28,8 +32,13 @@ #define ASSERT(_p) ((void)0) #endif +#define WPRINTK(fmt, args...) \ + printk(KERN_WARNING "xen_grant: " fmt, ##args) + + EXPORT_SYMBOL(gnttab_grant_foreign_access); EXPORT_SYMBOL(gnttab_end_foreign_access); +EXPORT_SYMBOL(gnttab_query_foreign_access); EXPORT_SYMBOL(gnttab_grant_foreign_transfer); EXPORT_SYMBOL(gnttab_end_foreign_transfer); @@ -39,6 +48,10 @@ static grant_ref_t gnttab_free_head; static grant_entry_t *shared; +/* /proc/xen/grant */ +static struct proc_dir_entry *grant_pde; + + /* * Lock-free grant-entry allocator */ @@ -84,9 +97,18 @@ gnttab_grant_foreign_access( return ref; } +int +gnttab_query_foreign_access( grant_ref_t ref ) +{ + u16 nflags; + + nflags = shared[ref].flags; + + return ( nflags & (GTF_reading|GTF_writing) ); +} + void -gnttab_end_foreign_access( - grant_ref_t ref, int readonly) +gnttab_end_foreign_access( grant_ref_t ref, int readonly ) { u16 flags, nflags; @@ -141,7 +163,72 @@ gnttab_end_foreign_transfer( return frame; } -void __init gnttab_init(void) +static int grant_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long data) +{ + int ret; + privcmd_hypercall_t hypercall; + + if ( cmd != IOCTL_PRIVCMD_HYPERCALL ) + return -ENOSYS; + + if ( copy_from_user(&hypercall, (void *)data, sizeof(hypercall)) ) + return -EFAULT; + + if ( hypercall.op != __HYPERVISOR_grant_table_op ) + return -ENOSYS; + + /* hypercall-invoking asm taken from privcmd.c */ + __asm__ __volatile__ ( + "pushl %%ebx; pushl %%ecx; pushl %%edx; pushl %%esi; pushl %%edi; " + "movl 4(%%eax),%%ebx ;" + "movl 8(%%eax),%%ecx ;" + "movl 12(%%eax),%%edx ;" + "movl 16(%%eax),%%esi ;" + "movl 20(%%eax),%%edi ;" + "movl (%%eax),%%eax ;" + TRAP_INSTR "; " + "popl %%edi; popl %%esi; popl %%edx; popl %%ecx; popl %%ebx" + : "=a" (ret) : "0" (&hypercall) : "memory" ); + + return ret; +} + +static struct file_operations grant_file_ops = { + ioctl: grant_ioctl, +}; + +static int grant_read(char *page, char **start, off_t off, + int count, int *eof, void *data) +{ + int len; + unsigned int i; + grant_entry_t *gt; + + gt = (grant_entry_t *)shared; + len = 0; + + for ( i = 0; i < NR_GRANT_REFS; i++ ) + if ( gt[i].flags ) + len += sprintf( page + len, + "Grant: ref (0x%x) flags (0x%hx) dom (0x%hx) frame (0x%x)\n", + i, + gt[i].flags, + gt[i].domid, + gt[i].frame ); + + *eof = 1; + return len; +} + +static int grant_write(struct file *file, const char __user *buffer, + unsigned long count, void *data) +{ + /* TODO: implement this */ + return -ENOSYS; +} + +static int __init gnttab_init(void) { gnttab_setup_table_t setup; unsigned long frame; @@ -160,4 +247,25 @@ void __init gnttab_init(void) set_fixmap_ma(FIX_GNTTAB, frame << PAGE_SHIFT); shared = (grant_entry_t *)fix_to_virt(FIX_GNTTAB); + + /* + * /proc/xen/grant : used by libxc to access grant tables + */ + if ( (grant_pde = create_xen_proc_entry("grant", 0600)) == NULL ) + { + WPRINTK("Unable to create grant xen proc entry\n"); + return -1; + } + + grant_file_ops.read = grant_pde->proc_fops->read; + grant_file_ops.write = grant_pde->proc_fops->write; + + grant_pde->proc_fops = &grant_file_ops; + + grant_pde->read_proc = &grant_read; + grant_pde->write_proc = &grant_write; + + return 0; } + +__initcall(gnttab_init); diff --git a/linux-2.6.10-xen-sparse/include/asm-xen/gnttab.h b/linux-2.6.10-xen-sparse/include/asm-xen/gnttab.h index fa166ec6b1..8c28c889f7 100644 --- a/linux-2.6.10-xen-sparse/include/asm-xen/gnttab.h +++ b/linux-2.6.10-xen-sparse/include/asm-xen/gnttab.h @@ -32,4 +32,8 @@ unsigned long gnttab_end_foreign_transfer( grant_ref_t ref); +int +gnttab_query_foreign_access( + grant_ref_t ref ); + #endif /* __ASM_GNTTAB_H__ */ diff --git a/linux-2.6.10-xen-sparse/include/asm-xen/hypervisor.h b/linux-2.6.10-xen-sparse/include/asm-xen/hypervisor.h index b82db08f70..b482eaa3c4 100644 --- a/linux-2.6.10-xen-sparse/include/asm-xen/hypervisor.h +++ b/linux-2.6.10-xen-sparse/include/asm-xen/hypervisor.h @@ -536,7 +536,7 @@ HYPERVISOR_grant_table_op( __asm__ __volatile__ ( TRAP_INSTR : "=a" (ret), "=b" (ign1), "=c" (ign2), "=d" (ign3) - : "0" (__HYPERVISOR_grant_table_op), "1" (cmd), "2" (count), "3" (uop) + : "0" (__HYPERVISOR_grant_table_op), "1" (cmd), "2" (uop), "3" (count) : "memory" ); return ret; diff --git a/tools/libxc/Makefile b/tools/libxc/Makefile index af40ec3d2d..516913b37f 100644 --- a/tools/libxc/Makefile +++ b/tools/libxc/Makefile @@ -20,6 +20,7 @@ SRCS += xc_atropos.c SRCS += xc_bvtsched.c SRCS += xc_domain.c SRCS += xc_evtchn.c +SRCS += xc_gnttab.c SRCS += xc_io.c SRCS += xc_linux_build.c SRCS += xc_plan9_build.c diff --git a/tools/libxc/xc.h b/tools/libxc/xc.h index 81d7b2ed3f..e37ce468a5 100644 --- a/tools/libxc/xc.h +++ b/tools/libxc/xc.h @@ -395,4 +395,61 @@ void *xc_map_foreign_batch(int xc_handle, u32 dom, int prot, int xc_get_pfn_list(int xc_handle, u32 domid, unsigned long *pfn_buf, unsigned long max_pfns); +/*\ + * GRANT TABLE FUNCTIONS +\*/ + +/** + * This function opens a handle to the more restricted grant table hypervisor + * interface. This may be used where the standard interface is not + * available because the domain is not privileged. + * This function can be called multiple times within a single process. + * Multiple processes can have an open hypervisor interface at the same time. + * + * Each call to this function should have a corresponding call to + * xc_grant_interface_close(). + * + * This function can fail if a Xen-enabled kernel is not currently running. + * + * @return a handle to the hypervisor grant table interface or -1 on failure + */ +int xc_grant_interface_open(void); + +/** + * This function closes an open grant table hypervisor interface. + * + * This function can fail if the handle does not represent an open interface or + * if there were problems closing the interface. + * + * @parm xc_handle a handle to an open grant table hypervisor interface + * @return 0 on success, -1 otherwise. + */ +int xc_grant_interface_close(int xc_handle); + +int xc_gnttab_map_grant_ref(int xc_handle, + memory_t host_virt_addr, + u32 dom, + u16 ref, + u16 flags, + s16 *handle, + memory_t *dev_bus_addr); + +int xc_gnttab_unmap_grant_ref(int xc_handle, + memory_t host_virt_addr, + memory_t dev_bus_addr, + u16 handle, + s16 *status); + +int xc_gnttab_setup_table(int xc_handle, + u32 dom, + u16 nr_frames, + s16 *status, + memory_t **frame_list); + +/* Grant debug builds only: */ +int xc_gnttab_dump_table(int xc_handle, + u32 dom, + s16 *status); + + #endif /* __XC_H__ */ diff --git a/tools/libxc/xc_gnttab.c b/tools/libxc/xc_gnttab.c new file mode 100644 index 0000000000..2601c30f60 --- /dev/null +++ b/tools/libxc/xc_gnttab.c @@ -0,0 +1,143 @@ +/****************************************************************************** + * xc_gnttab.c + * + * API for manipulating and accessing grant tables + * + * Copyright (c) 2005 Christopher Clark + * based on xc_evtchn.c Copyright (c) 2004, K A Fraser. + */ + +#include "xc_private.h" +#include "xen/grant_table.h" + +static int +do_gnttab_op( int xc_handle, + unsigned long cmd, + gnttab_op_t *op, + unsigned long count ) +{ + int ret = -1; + privcmd_hypercall_t hypercall; + + hypercall.op = __HYPERVISOR_grant_table_op; + hypercall.arg[0] = cmd; + hypercall.arg[1] = (unsigned long)(op); + hypercall.arg[2] = count; + + if ( mlock(op, sizeof(*op)) != 0 ) + { + PERROR("Could not lock memory for Xen hypercall"); + goto out1; + } + + if ( (ret = do_xen_hypercall(xc_handle, &hypercall)) < 0 ) + { + printf("do_gnttab_op: hypercall returned error %d\n", ret); + goto out2; + } + + out2: (void)munlock(op, sizeof(*op)); + out1: return ret; +} + + +int xc_gnttab_map_grant_ref(int xc_handle, + memory_t host_virt_addr, + u32 dom, + u16 ref, + u16 flags, + s16 *handle, + memory_t *dev_bus_addr) +{ + gnttab_op_t op; + int rc; + + op.u.map_grant_ref.host_virt_addr = host_virt_addr; + op.u.map_grant_ref.dom = (domid_t)dom; + op.u.map_grant_ref.ref = ref; + op.u.map_grant_ref.flags = flags; + + if ( (rc = do_gnttab_op(xc_handle, GNTTABOP_map_grant_ref, &op, 1)) == 0 ) + { + *handle = op.u.map_grant_ref.handle; + *dev_bus_addr = op.u.map_grant_ref.dev_bus_addr; + } + + return rc; +} + + +int xc_gnttab_unmap_grant_ref(int xc_handle, + memory_t host_virt_addr, + memory_t dev_bus_addr, + u16 handle, + s16 *status) +{ + gnttab_op_t op; + int rc; + + op.u.unmap_grant_ref.host_virt_addr = host_virt_addr; + op.u.unmap_grant_ref.dev_bus_addr = dev_bus_addr; + op.u.unmap_grant_ref.handle = handle; + + if ( (rc = do_gnttab_op(xc_handle, GNTTABOP_unmap_grant_ref, &op, 1)) == 0 ) + *status = op.u.unmap_grant_ref.status; + + return rc; +} + +int xc_gnttab_setup_table(int xc_handle, + u32 dom, + u16 nr_frames, + s16 *status, + memory_t **frame_list) +{ + gnttab_op_t op; + int rc; + int i; + + op.u.setup_table.dom = (domid_t)dom; + op.u.setup_table.nr_frames = nr_frames; + + if ( (rc = do_gnttab_op(xc_handle, GNTTABOP_setup_table, &op, 1)) == 0 ) + { + *status = op.u.setup_table.status; + for ( i = 0; i < nr_frames; i++ ) + { + (*frame_list)[i] = op.u.setup_table.frame_list[i]; + } + } + + return rc; +} + +int xc_gnttab_dump_table(int xc_handle, + u32 dom, + s16 *status) +{ + gnttab_op_t op; + int rc; + + op.u.dump_table.dom = (domid_t)dom; + + printf("xc_gnttab_dump_table: domain %d\n", dom); + + if ( (rc = do_gnttab_op(xc_handle, GNTTABOP_dump_table, &op, 1)) == 0 ) + *status = op.u.dump_table.status; + + return rc; +} + +int xc_grant_interface_open(void) +{ + int fd = open("/proc/xen/grant", O_RDWR); + if ( fd == -1 ) + PERROR("Could not obtain handle on grant command interface"); + return fd; + +} + +int xc_grant_interface_close(int xc_grant_handle) +{ + return close(xc_grant_handle); +} diff --git a/tools/libxc/xc_vmx_build.c b/tools/libxc/xc_vmx_build.c index 3bb4d4fde8..382d87f9b3 100644 --- a/tools/libxc/xc_vmx_build.c +++ b/tools/libxc/xc_vmx_build.c @@ -465,10 +465,10 @@ int vmx_identify(void) { int eax, ecx; - __asm__ __volatile__ ("cpuid" + __asm__ __volatile__ ("pushl %%ebx; cpuid; popl %%ebx" : "=a" (eax), "=c" (ecx) : "0" (1) - : "bx", "dx"); + : "dx"); if (!(ecx & VMX_FEATURE_FLAG)) { return -1; } diff --git a/xen/common/grant_table.c b/xen/common/grant_table.c index 3eb21f7d71..edc6171f16 100644 --- a/xen/common/grant_table.c +++ b/xen/common/grant_table.c @@ -110,6 +110,8 @@ __gnttab_map_grant_ref( (void)__put_user(GNTST_no_device_space, &uop->handle); return; } + DPRINTK("Mapping grant ref (%hu) for domain (%hu) with flags (%x)\n", + ref, dom, flags); act = &rd->grant_table->active[ref]; sha = &rd->grant_table->shared[ref]; @@ -324,6 +326,8 @@ __gnttab_unmap_grant_ref( (void)__put_user(GNTST_bad_domain, &uop->status); return; } + DPRINTK("Unmapping grant ref (%hu) for domain (%hu) with handle (%hu)\n", + ref, dom, handle); act = &rd->grant_table->active[ref]; sha = &rd->grant_table->shared[ref]; @@ -423,7 +427,7 @@ gnttab_setup_table( { ASSERT(d->grant_table != NULL); (void)put_user(GNTST_okay, &uop->status); - (void)put_user(virt_to_phys(d->grant_table) >> PAGE_SHIFT, + (void)put_user(virt_to_phys(d->grant_table->shared) >> PAGE_SHIFT, &uop->frame_list[0]); } @@ -431,14 +435,99 @@ gnttab_setup_table( return 0; } +#ifdef GRANT_DEBUG +static int +gnttab_dump_table(gnttab_dump_table_t *uop) +{ + grant_table_t *gt; + gnttab_dump_table_t op; + struct domain *d; + u32 shared_mfn; + active_grant_entry_t *act; + grant_entry_t sha_copy; + grant_mapping_t *maptrack; + int i; + + + if ( unlikely(copy_from_user(&op, uop, sizeof(op)) != 0) ) + { + DPRINTK("Fault while reading gnttab_dump_table_t.\n"); + return -EFAULT; + } + + if ( op.dom == DOMID_SELF ) + { + op.dom = current->domain->id; + } + + if ( unlikely((d = find_domain_by_id(op.dom)) == NULL) ) + { + DPRINTK("Bad domid %d.\n", op.dom); + (void)put_user(GNTST_bad_domain, &uop->status); + return 0; + } + + ASSERT(d->grant_table != NULL); + gt = d->grant_table; + (void)put_user(GNTST_okay, &uop->status); + + shared_mfn = virt_to_phys(d->grant_table->shared); + + DPRINTK("Grant table for dom (%hu) MFN (%x)\n", + op.dom, shared_mfn); + + spin_lock(>->lock); + + ASSERT(d->grant_table->active != NULL); + ASSERT(d->grant_table->shared != NULL); + + for ( i = 0; i < NR_GRANT_ENTRIES; i++ ) + { + act = >->active[i]; + sha_copy = gt->shared[i]; + + if ( act->pin || act->domid || act->frame || + sha_copy.flags || sha_copy.domid || sha_copy.frame ) + { + DPRINTK("Grant: dom (%hu) ACTIVE (%d) pin:(%x) dom:(%hu) frame:(%u)\n", + op.dom, i, act->pin, act->domid, act->frame); + DPRINTK("Grant: dom (%hu) SHARED (%d) flags:(%hx) dom:(%hu) frame:(%u)\n", + op.dom, i, sha_copy.flags, sha_copy.domid, sha_copy.frame); + + } + + } + + ASSERT(d->grant_table->maptrack != NULL); + + for ( i = 0; i < NR_MAPTRACK_ENTRIES; i++ ) + { + maptrack = >->maptrack[i]; + + if ( maptrack->ref_and_flags & MAPTRACK_GNTMAP_MASK ) + { + DPRINTK("Grant: dom (%hu) MAP (%d) ref:(%hu) flags:(%x) dom:(%hu)\n", + op.dom, i, + maptrack->ref_and_flags >> MAPTRACK_REF_SHIFT, + maptrack->ref_and_flags & MAPTRACK_GNTMAP_MASK, + maptrack->domid); + } + } + + spin_unlock(>->lock); + + put_domain(d); + return 0; +} +#endif + long do_grant_table_op( unsigned int cmd, void *uop, unsigned int count) { long rc; - /* XXX stubbed out XXX */ - return -ENOSYS; + DPRINTK("Grant: table operation (%u) count: (%u)\n", cmd, count); if ( count > 512 ) return -EINVAL; @@ -462,6 +551,11 @@ do_grant_table_op( case GNTTABOP_setup_table: rc = gnttab_setup_table((gnttab_setup_table_t *)uop, count); break; +#ifdef GRANT_DEBUG + case GNTTABOP_dump_table: + rc = gnttab_dump_table((gnttab_dump_table_t *)uop); + break; +#endif default: rc = -ENOSYS; break; @@ -607,6 +701,72 @@ grant_table_create( return -ENOMEM; } +static void +gnttab_release_all_mappings(grant_table_t *gt) +{ + grant_mapping_t *map; + domid_t dom; + grant_ref_t ref; + u16 handle, i; + struct domain *ld, *rd; + unsigned long frame; + active_grant_entry_t *act; + grant_entry_t *sha; + + ld = current->domain; + + for ( handle = 0; handle < NR_MAPTRACK_ENTRIES; handle++ ) + { + map = >->maptrack[handle]; + + if ( map->ref_and_flags & MAPTRACK_GNTMAP_MASK ) + { + dom = map->domid; + ref = map->ref_and_flags >> MAPTRACK_REF_SHIFT; + + DPRINTK("Grant release (%hu) ref:(%hu) flags:(%x) dom:(%hu)\n", + handle, ref, + map->ref_and_flags & MAPTRACK_GNTMAP_MASK, dom); + + if ( unlikely((rd = find_domain_by_id(dom)) == NULL) || + unlikely(ld == rd) ) + { + if ( rd != NULL ) + put_domain(rd); + /* TODO: need to be able to handle domains destroyed + * with active mappings. + */ + DPRINTK("Grant release: Could not find domain %d\n", dom); + continue; + } + + act = &rd->grant_table->active[ref]; + sha = &rd->grant_table->shared[ref]; + + spin_lock(&rd->grant_table->lock); + + frame = act->frame; + + for ( i = ((act->pin & GNTPIN_hstw_mask) >> GNTPIN_hstw_shift) + + ((act->pin & GNTPIN_devw_mask) >> GNTPIN_devw_shift); + i > 0; i-- ) + { + put_page_type(&frame_table[frame]); + } + act->pin = 0; + + put_page(&frame_table[frame]); + + clear_bit(_GTF_reading, &sha->flags); + clear_bit(_GTF_writing, &sha->flags); + + spin_unlock(&rd->grant_table->lock); + + put_domain(rd); + } + } +} + void grant_table_destroy( struct domain *d) @@ -615,6 +775,9 @@ grant_table_destroy( if ( (t = d->grant_table) != NULL ) { + if ( t->maptrack != NULL ) + gnttab_release_all_mappings(t); + /* Free memory relating to this grant table. */ d->grant_table = NULL; free_xenheap_page((unsigned long)t->shared); @@ -629,6 +792,7 @@ grant_table_init( void) { /* Nothing. */ + DPRINTK("Grant table init\n"); } /* diff --git a/xen/include/public/grant_table.h b/xen/include/public/grant_table.h index 389e082646..718d226709 100644 --- a/xen/include/public/grant_table.h +++ b/xen/include/public/grant_table.h @@ -206,6 +206,19 @@ typedef struct { MEMORY_PADDING; } PACKED gnttab_setup_table_t; /* 16 bytes */ +/* + * GNTTABOP_dump_table: Dump the contents of the grant table to the + * xen console. Debugging use only. + */ +#define GNTTABOP_dump_table 3 +typedef struct { + /* IN parameters. */ + domid_t dom; /* 0 */ + /* OUT parameters. */ + s16 status; /* 2: GNTST_* */ +} PACKED gnttab_dump_table_t; /* 4 bytes */ + + /* * Bitfield values for update_pin_status.flags. */ @@ -247,5 +260,15 @@ typedef struct { "permission denied" \ } + +typedef struct { + union { /* 0 */ + gnttab_map_grant_ref_t map_grant_ref; + gnttab_unmap_grant_ref_t unmap_grant_ref; + gnttab_setup_table_t setup_table; + gnttab_dump_table_t dump_table; + u8 __dummy[24]; + } PACKED u; +} PACKED gnttab_op_t; /* 32 bytes */ #endif /* __XEN_PUBLIC_GRANT_TABLE_H__ */ diff --git a/xen/include/xen/grant_table.h b/xen/include/xen/grant_table.h index c161667cdf..2a484c4a29 100644 --- a/xen/include/xen/grant_table.h +++ b/xen/include/xen/grant_table.h @@ -27,6 +27,8 @@ #include #include +#define GRANT_DEBUG 1 + /* Active grant entry - used for shadowing GTF_permit_access grants. */ typedef struct { u32 pin; /* Reference count information. */ -- 2.30.2